package Client;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;

import Server.IServer;

public class Client extends UnicastRemoteObject implements IClient {
	
	private static final long serialVersionUID = 1L;
	/**
	 * Pseudo du client
	 */
	private String clientName;
	/**
	 * Identifiant du client, invariant, unique
	 */
	private String login;
	/**
	 * Reference vers l'interface du server
	 */
	private IServer serveurDistant;
	/**
	 * GUI de l'application Cliente
	 */
	private MainWindow mainAltWindow;
	
	/**
	 * Liste des sujets affiches sur le client
	 */
	List<String> subjects = null;
	
	/**
	 * Methods call by the GUI when user click on the button to open a forum
	 * @param subject : name of the subject which must be open
	 * @throws RemoteException
	 */
	public void openSubject(String subject) throws RemoteException {
		serveurDistant.abonneMoi(this.login, subject);
		
	}
	
	/**
	 * Method call by the GUI when user click on the buton QUIT
	 * @param subject : name of the sujet which must be leave by client
	 */
	public void closeSubject(String subject) {
		try {
			serveurDistant.desabonneMoi(login, subject);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Default constructor of the Client
	 * @param log : the unique id of the client
	 * @throws RemoteException
	 */
	public Client(String log) throws RemoteException {
		clientName = "Anonymous" + (int) Math.ceil(Math.random()*100);
		this.login = log;
	}
	
	/**
	 * Add a subject to the server in three step (like pseudo, ndrl)
	 * 1) Ask server if this subject already exit
	 * 2) The server try to add this new subject, he change the name if he's already use
	 * 3) The Client application make automaticaly the refresh to know the new subject (other client must do this refresh manualy)
	 */
	public void addSubjectFromWindow(String subject) {
		try {
			serveurDistant.addSubject(subject);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		this.refresh();
	}
	
	/**
	 * Client ask server to know all the subjects, and say to this GUI the change
	 */
	public void refresh() {
		try {
			subjects = serveurDistant.getSubjects();
			mainAltWindow.updateSubjects();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Set the name of the client in three step
	 * 1) Ask server if this name already exit
	 * 2) The server answer with a String, the name which is allow to use
	 * 3) The client take this name for him
	 */
	public void setName(String name){
		String correctName = "";
		try {
			correctName = serveurDistant.chooseName(this.login, this.clientName, name);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		
		this.clientName = correctName;
	}
	
	/**
	 * 
	 * @param s
	 */
	public void setServer(IServer s){
		serveurDistant = s;
		try {
			serveurDistant.binder(this.login);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		
		subjects = null;
		
		try {
			subjects = serveurDistant.getSubjects();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 */
	public void genWindow(){
		mainAltWindow = new MainWindow(this);
		mainAltWindow.setVisible(true);
	}

	/**
	 * methode remote appelee par le serveur pour diffuser un message
	 */
	public void publierMessage(String sujet, String message) throws RemoteException {
		this.mainAltWindow.publish(sujet, message);
	}

	/**
	 * Methode appelee par l'interface graphique pour que le client demande au serveur de diffuser le message
	 * @param name
	 * @param text
	 * @throws RemoteException
	 */
	public void diffuserMessage(String fenetre, String text) throws RemoteException {
		serveurDistant.diffuserMessage(fenetre , clientName + " said : " + text);
	}

	/**
	 * 
	 * @return
	 */
	public String getName() {
		return clientName;
	}

	/**
	 * 
	 * @return
	 */
	public List<String> getSubjects() {
		return this.subjects;
	}

	/**
	 * 
	 */
	public String getLogin() {
		return this.login;
	}
}
